package com.brsanthu.sgwidgets.client;

import java.util.Date;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.URL;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.DragAppearance;
import com.smartgwt.client.types.ListGridEditEvent;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.ImgButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.PasswordItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.TextAreaItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionEvent;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.Layout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.tab.Tab;

public class ClientUtils {
    public static final Integer ENTER_KEY = 13;
    private static DateTimeFormat dfDateTime = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
    private static DateTimeFormat dfDate = DateTimeFormat.getFormat("MM/dd/yyyy");
    private static FormItemIcon icon = null;

    public static void fillComboBox(DynamicForm form, String fieldName, List<String> values) {

        if (values == null) {
            return;
        }
        ComboBoxItem item = (ComboBoxItem) form.getField(fieldName);
        item.setValueMap(values.toArray(new String[values.size()]));

    }

    public static <T> void removeAndAddRecords(ListGrid grid, List<T> list, GridRecordMapper<T> mapper) {
        removeRecords(grid);
        addRecords(grid, list, mapper);
    }

    public static <T> void addRecords(ListGrid grid, List<T> list, GridRecordMapper<T> mapper) {
        if (list == null) {
            return;
        }

        for (T t : list) {
            ListGridRecord record = new ListGridRecord();
            record.setAttribute("sourceObject", t);
            grid.addData(mapper.mapRecord(record, t));
        }
        
        selectGridIfSingleRecord(grid);
    }

    public static <T> void addRecord(ListGrid grid, T object, GridRecordMapper<T> mapper) {
        ListGridRecord record = new ListGridRecord();
        record.setAttribute("sourceObject", object);
        grid.addData(mapper.mapRecord(record, object));
        
        selectGridIfSingleRecord(grid);
    }


    public static boolean isEmpty(String text) {
        return text == null || text.trim().length() == 0;
    }

    public static boolean isNotEmpty(String text) {
        return !(text == null || text.trim().length() == 0);
    }

    public static boolean isEmpty(Map map) {
        return map == null || map.isEmpty();
    }

    public static boolean isEmpty(List list) {
        return list == null || list.isEmpty();
    }

    public static void removeRecords(ListGrid grid) {
        grid.deselectAllRecords();
        for (Record record : grid.getRecords()) {
            grid.removeData(record);
        }
        
        grid.selectRecords((Record[]) null, false);
    }

    public static void removeSelectedRecords(ListGrid grid) {
        for (Record record : grid.getSelection()) {
            grid.removeData(record);
        }
    }

    public static Label createH3Label(String title) {
        return createH3Label(title, "100%");
    }
    public static Label createH3Label(String title, String width) {
        Label label = createLabel(title);
        label.setWidth(width);
        label.setStyleName("sgwidgetsH3Title");
        return label;
    }

    public static Label createSectionLabel(String title) {
        Label label = createLabel(title);
        label.setStyleName("sgwidgetsSection");
        return label;
    }

    public static Label createH2Label(String title) {
        Label label = createLabel(title);
        label.setStyleName("sgwidgetsH2Title");
        return label;
    }

    public static Label createH1Label(String title) {
        Label label = createLabel(title);
        label.setStyleName("sgwidgetsH1Title");
        return label;
    }

    public static Label createSpacer(int height) {
        Label label = createLabel();
        label.setPadding(0);
        label.setHeight(height);
        return label;
    }

    public static Label createDescriptionLabel(String description) {
        Label label = createLabel(description);
        label.setStyleName("sgwidgetsDescription");
        return label;
    }

    public static Label createSubDescriptionLabel(String description) {
        Label label = createLabel(description);
        label.setStyleName("sgwidgetsSubDescription");
        return label;
    }

    public static Label createLabel(String text) {
        Label label = createLabel();
        label.setContents(text);
        return label;
    }

    public static Label createLabel() {
        Label label = new Label();
        label.setCanSelectText(true);
        label.setPadding(3);
        label.setAutoHeight();
        label.setValign(VerticalAlignment.TOP);
        label.setAlign(Alignment.LEFT);
        return label;
    }

    public static Layout createButtonBar(Button... buttons) {
        return createButtonBar(-1, buttons);
    }

    public static Layout createButtonBar(int limit, Button... buttons) {
        
        VLayout vlayout = createVLayout(5, (Canvas[]) null);
        vlayout.setMargin(10);
        vlayout.setHeight(0);
        
        if (buttons == null) {
            return vlayout;
        }
        
        HLayout buttonBar = null;
        
        for (int i = 0; i < buttons.length; i++) {
            
            if (limit >= 0 && i != 0 && i % limit == 0) {
                vlayout.addMember(buttonBar);
                buttonBar = null;
            }

            if (buttonBar == null) {
                buttonBar = new HLayout();
                buttonBar.setAlign(Alignment.CENTER);
                buttonBar.setMembersMargin(10);
                buttonBar.setWidth100();
                buttonBar.setHeight("35");
            }
            
            buttonBar.addMember(buttons[i]);
        }
        
        if (buttonBar != null) {
            vlayout.addMember(buttonBar);
        }
        
        vlayout.setHeight(vlayout.getMembers().length * 35);
        
        return vlayout;
    }

    public static Window createWindow(String title) {
        Window window = new Window();
        window.setTitle(title);
        window.setShowEdges(true);
        //window.setKeepInParentRect(true);
        window.setCanSelectText(true);
        window.setShowCloseButton(false);
        window.setShowMinimizeButton(false);
        window.setWidth100();
        window.setHeight100();
        window.setAutoCenter(true);
        window.setDragAppearance(DragAppearance.NONE);
        return window;
    }

    public static FormItemIcon createFormIcon() {
        if (icon == null) {
            icon = new FormItemIcon();
            icon.setSrc("silk/help.png");
            icon.setNeverDisable(true);
        }

        return icon;
    }

    public static Label createErrorLabel(String text) {
        Label errorLabel = createErrorLabel();
        errorLabel.setContents(text);
        return errorLabel;
    }

    public static Label createErrorLabel() {
        Label label = createLabel();
        label.setStyleName("sgwidgetsError");
        return label;
    }

    public static Label createInfoLabel() {
        Label label = createLabel();
        label.setStyleName("sgwidgetsInfo");
        return label;
    }

    public static ImgButton createImgButton(String file) {
        ImgButton btnImg = new ImgButton();
        btnImg.setShowRollOverIcon(false);
        btnImg.setShowRollOver(false);
        btnImg.setSrc(file);
        btnImg.setWidth(16);
        btnImg.setHeight(16);

        return btnImg;
    }

    public static ListGrid createListGrid(String name, String title, List<String> values, String height, String width, String emptyMessage) {
        ListGrid list = createListGrid();
        list.setHeight(height);
        list.setWidth(width);
        
        ListGridField field = new ListGridField(name, "<b>"+title+"<b/>");
        list.setFields(field);
        
        addRecordsFromList(list, name, values);
        
        list.setEmptyMessage(emptyMessage);
        return list;
    }

    public static ListGrid removeAndAddRecordsFromList(ListGrid grid, String name, List<String> values) {
        
        debug("Values are " + values);
        
        removeRecords(grid);
        addRecordsFromList(grid, name, values);
        
        return grid;
    }

    
    public static ListGrid addRecordsFromList(ListGrid grid, String name, List<String> values) {

        if (values == null) {
            return grid;
        }

        for (String value : values) {
            ListGridRecord record = new ListGridRecord();
            record.setAttribute(name, value);
            grid.addData(record);
        }

        selectGridIfSingleRecord(grid);
        
        return grid;
    }

    public static ListGridField createListGridField(String name, String title, int width) {
        return new ListGridField(name, "<b>" + title + "</b>", width);
    }
    public static ListGridField createListGridField(String name, String title) {
        return new ListGridField(name, "<b>" + title + "</b>");
    }

    public static ListGridField createListGridFieldLink(String name, String title) {
        ListGridField field = createListGridField(name, title);
        field.setType(ListGridFieldType.LINK);
        return field;
    }
    public static ListGridField createListGridFieldLink(String name, String title, int width) {
        ListGridField field = createListGridField(name, title, width);
        field.setType(ListGridFieldType.LINK);
        return field;
    }
    public static StaticTextItem createStaticTextItem(String name, String title) {
        return new StaticTextItem(name, "<b>" + title + "</b>");
    }

    public static StaticTextItem createStaticTextItemLink(String name, String title, com.smartgwt.client.widgets.form.fields.events.ClickHandler handler) {
        StaticTextItem item = createStaticTextItem(name, title);
        item.setCellStyle("textlink");
        item.addClickHandler(handler);

        return item;
    }

    public static TextItem createRequiredTextItem(String name, String title, String witdh) {
        TextItem item = getRequiredTextItem(name, title, true);
        item.setWidth(witdh);
        return item;
    }
    public static TextItem createRequiredTextItem(String name, String title) {
        return getRequiredTextItem(name, title, true);
    }
    public static TextItem getRequiredTextItem(String name, String title, boolean wrap) {
        TextItem item = new TextItem(name, title);
        item.setWrapTitle(wrap);
        item.setRequired(true);
        return item;
    }

    public static TextItem createTextItem(String name, String title, boolean required) {
        return createTextItem(name, title, required, "200");
    }

    public static TextItem createTextItem(String name, String title, boolean required, String width) {
        TextItem item = new TextItem(name, title);
        item.setRequired(required);

        if (width != null) {
            item.setWidth(width);
        }
        return item;
    }

    public static void setReadOnly(TextItem item) {
        item.setAttribute("readOnly", "true");
    }
    public static TextItem createPasswordItem(String name, String title, boolean required, String width) {
        PasswordItem item = new PasswordItem(name, title);
        item.setRequired(required);

        if (width != null) {
            item.setWidth(width);
        }
        return item;
    }

    public static TextAreaItem createTextAreaItem(String name, String title, String width) {
        TextAreaItem item = new TextAreaItem(name, title);
        item.setWidth(width);
        return item;
    }

    public static ComboBoxItem createComboBoxItem(String name, String title) {
        return createComboBoxItem(name, title, false, true, null);
    }

    public static ComboBoxItem createComboBoxItem(String name, String title, boolean required) {
        return createComboBoxItem(name, title, required, true, null);
    }

    public static ComboBoxItem createComboBoxItem(String name, String title, boolean required, boolean wrapTitle) {
        return createComboBoxItem(name, title, required, wrapTitle, null);
    }

    public static ComboBoxItem createComboBoxItem(String name, String title, boolean required, boolean wrapTitle, String[] values) {
        ComboBoxItem item = new ComboBoxItem(name, title);
        item.setRequired(required);
        item.setWrapTitle(wrapTitle);

        if (values != null) {
            item.setValueMap(values);
        }

        return item;
    }

    public static void removeChildren(Layout window) {
        Canvas[] children = window.getChildren();
        for (int i = 0; i < children.length; i++) {
            window.removeChild(children[i]);
        }
    }

    public static void removeMembers(Layout window) {
        Canvas[] children = window.getMembers();
        for (int i = 0; i < children.length; i++) {
            window.removeMember(children[i]);
            children[i].destroy();
        }
    }

    public static Label createSuccessLabel() {
        Label label = createLabel();
        label.setStyleName("sgwidgetsSuccess");
        return label;
    }

    public static String formatDateTime(Date date) {
        if (date == null) {
            return "";
        }
        return dfDateTime.format(date);
    }
    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        return dfDate.format(date);
    }

    public static String formatYesorNo(boolean value) {
        return value?"Yes":"No";
    }

    public static VLayout createVLayout(int margin) {
        return createVLayout(margin, (Canvas[]) null);
    }
    public static VLayout createVLayout(Canvas... items) {
        return createVLayout(5, items);
    }
    public static VLayout createVLayout(int margin, Canvas... items) {
        return createVLayout(margin, "100%", "100%", items);
    }
    public static VLayout createVLayout(int margin, String width, String height) {
        return createVLayout(margin, width, height, (Canvas[]) null);
    }
    public static VLayout createVLayout(int margin, String width, String height, Canvas... items) {
        VLayout vlayout = new VLayout(margin);
        vlayout.setWidth(width);
        vlayout.setHeight(height);

        if (items != null) {
            for (Canvas canvas : items) {
                vlayout.addMember(canvas);
            }
        }

        return vlayout;
    }
    public static HLayout createHLayout(Canvas... items) {
        return createHLayout(5, items);
    }
    public static HLayout createHLayout(int margin) {
        return createHLayout(margin, (Canvas[]) null);
    }
    public static HLayout createHLayout(int margin, Canvas... items) {
        return createHLayout(margin, "100%", "100%", items);
    }
    public static HLayout createHLayout(int margin, String width, String height) {
        return createHLayout(margin, width, height, (Canvas[])null);
    }
    public static HLayout createHLayout(int margin, String width, String height, Canvas... items) {
        HLayout hlayout = new HLayout(margin);
        hlayout.setWidth(width);
        hlayout.setHeight(height);

        if (items != null) {
            for (Canvas canvas : items) {
                hlayout.addMember(canvas);
            }
        }

        return hlayout;
    }

    public static Canvas applyBorder(Canvas canvas) {
        canvas.setBorder("1px solid #A7ABB4");

        return canvas;
    }

    public static ListGrid createListGrid(String emptyMessage) {
        ListGrid grid = createListGrid();
        grid.setEmptyMessage(emptyMessage);
        return grid;
    }


    public static ListGrid createListGridWithLinkText(final String... fields) {
        final ListGrid grid = new ListGrid() {
            @Override
            protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
                for (String field : fields) {
                    if (getFieldName(colNum).equals(field)) {
                        return "text-decoration: underline; color:#0000EE; cursor: hand";
                    }
                }
                return super.getCellCSSText(record, rowNum, colNum);
            }
        };
        grid.setBaseStyle("myOtherGridCell");
        grid.setCanEdit(true);
        grid.setEditByCell(true);
        grid.setEditEvent(ListGridEditEvent.CLICK);

        return grid;
    }

    public static String emptyIfNull(Object value) {
        if (value == null) {
            return "";
        }

        return value.toString();
    }


    public static Layout createSection(String title, Canvas canvas) {
        return createSection(title, "100%", "100%", canvas);
    }
    public static Layout createSection(String title, String width, String height, Canvas canvas) {
        canvas.setBorder("0px");
        Label sectionTitle = createSectionLabel(title);
        VLayout vLayout = createVLayout(0, width, height, sectionTitle, canvas);
        applyBorder(vLayout);

        return vLayout;
    }

    public static String getStringIfEmpty(String input, String stringIfNull) {
        if (isEmpty(input)) {
            return stringIfNull;
        }

        return input;
    }

    public static String getPayloadUrl(String payloadType, String payloadId) {
        return GWT.getModuleBaseURL() +  "servletPayloadLookup?payloadType=" +  payloadType + "&payloadId=" + URL.encodeComponent(payloadId) + "&formatXml=true";
    }

    public static DynamicForm createForm(String width, String height, int numOfCols, boolean wrapTitles) {
        DynamicForm form = new DynamicForm();
        form.setWrapItemTitles(wrapTitles);
        form.setWidth(width);
        form.setHeight(height);
        form.setNumCols(numOfCols);

        return form;
    }

    public static SelectItem createSelectItem(String name, String title, boolean allowEmptyValues, List<String> values, boolean selectFirstValue) {

        GWT.log("Setting values " + values);
        SelectItem item = createSelectItem(name, title, allowEmptyValues, values==null?null:values.toArray(new String[values.size()]));
        item.setDefaultToFirstOption(selectFirstValue);

        return item;
    }

    public static SelectItem createSelectItem(String name, String title, boolean allowEmptyValues, String[] values) {
        SelectItem selectItem = new SelectItem(name, title);
        selectItem.setAllowEmptyValue(allowEmptyValues);

        if (values != null && values.length > 0) {
            selectItem.setValueMap(values);
        }

        return selectItem;
    }

    public static ButtonItem createButtonItem(String name, String title, String width) {
        return createButtonItem(name, title, width, null);
    }
    
    public static ButtonItem createButtonItem(String name, String title, String width, String icon) {
        ButtonItem buttonItem = new ButtonItem(name, bold(title));
        buttonItem.setIcon(icon);
        buttonItem.setWidth(width);
        buttonItem.setStartRow(false);
        buttonItem.setEndRow(false);

        return buttonItem;
    }

    public static void assignDefaultFunction(final Runnable runnable, DynamicForm form) {
        assignDefaultFunction(runnable, form.getFields());
    }

    
    public static void assignDefaultFunction(final Runnable runnable, FormItem... items) {
        KeyPressHandler keyPressHandler = new KeyPressHandler() {
            @Override
            public void onKeyPress(KeyPressEvent event) {
                if (event.getCharacterValue() == ENTER_KEY) {
                    runnable.run();
                }
            }
        };

        if (items != null) {
            for (FormItem item : items) {
                item.addKeyPressHandler(keyPressHandler);
            }
        }
    }

    public static void assignDefaultButton(final ButtonItem button, FormItem... items) {
        
        KeyPressHandler keyPressHandler = new KeyPressHandler() {
            @Override
            public void onKeyPress(KeyPressEvent event) {
                if (event.getCharacterValue() == ENTER_KEY) {
                    button.fireEvent(new ClickEvent(null));
                }
            }
        };

        if (items != null) {
            for (FormItem item : items) {
                item.addKeyPressHandler(keyPressHandler);
            }
        }
    }
    
    public static void setListGridSelectionButtons (final ListGrid grid, final Canvas... canvas) {
        grid.addSelectionChangedHandler(new SelectionChangedHandler() {
            @Override
            public void onSelectionChanged(SelectionEvent event) {
                enableDisable(getSelectedObject(grid) != null, canvas);
            }
        });
    }
    
    public static ListGrid createListGrid() {
        return createListGrid("100%", "100%");
    }

    public static ListGrid createListGrid(String width, String height) {
        final ListGrid grid = new ListGrid();
        grid.setCanEdit(true);
        grid.setEditByCell(true);
        grid.setEditEvent(ListGridEditEvent.DOUBLECLICK);
        grid.setBaseStyle("myOtherGridCell");
        grid.setShowAllRecords(true);
        grid.setAlternateRecordStyles(true);
        grid.setSelectionType(SelectionStyle.SINGLE);
        grid.setWidth(width);
        grid.setHeight(height);
        return grid;
    }

    public static Object getSelectedObject(ListGrid grid) {
        Object object = null;

        ListGridRecord record = grid.getSelectedRecord();

        if (record != null) {
            object = record.getAttributeAsObject("sourceObject");
        }

        return object;
    }

    public static Tab createTab(String name, String title, String icon, int width) {
        Tab tab = new Tab();
        tab.setID(name);
        tab.setTitle(title);
        tab.setIcon(icon);
        tab.setWidth(width);

        return tab;
    }

    public static Button createButton (String title, ClickHandler handler) {
        return createButton(title, false, handler);
    }

    public static Button createButton (String title, boolean disabled, ClickHandler handler) {
        Button btn = new Button(bold(title));
        
        //We are trying to make this minimum 50 chars width.
        btn.setWidth(Math.max(title.length() * 7 + 10, 100));

        if (disabled) {
            btn.disable();
        }

        if (handler != null) {
            btn.addClickHandler(handler);   
        }

        return btn;
    }

    public static ButtonItem createButtonItem (String title, boolean disabled, String icon, String width, com.smartgwt.client.widgets.form.fields.events.ClickHandler handler) {

        ButtonItem btn = new ButtonItem(title, bold(title));
        btn.setIcon(icon);
        btn.setEndRow(false);
        btn.setWidth(width);

        if (disabled) {
            btn.disable();
        }

        btn.addClickHandler(handler);

        return btn;
    }


    public static String bold(String inString) {
        return "<b>" +  inString + "</b>";
    }

    public static CheckboxItem createCheckBoxItem(String name, String title, boolean checked) {
        CheckboxItem checkBoxItem = new CheckboxItem(name, title);
        checkBoxItem.setValue(checked);

        return checkBoxItem;

    }

    public static void enableDisable(boolean enabled, Canvas... canvases) {
        
        if (canvases == null) {
            return;
        }
        
        for (Canvas canvas : canvases) {
            if (enabled) {
                canvas.enable();
            } else {
                canvas.disable();
            }
        }
    }
    
    public static String getSearchLimitText(int limit) {
        return "Please note that due to performance limitations, only " + limit +" matched records are returned.";
    }
    
    public static String getSearchResultText(int result, int limit) {
        
        if (result == 0) {
            return "Searched returned no results. Please refine the search criteria.";
        } else if (result == limit) {
            return "Search returned maximum allowed (" + limit + ") number of records so there may be more records matching the criteria.";
        }
        
        return "Search returned " + result + " records.";
    }
    
    public static String getStackTrace(Object[] stackTrace) {
        String output = "";
        for (Object line : stackTrace) {
          output += line + "<br/>";
        }
        return output;
    }
    
    public static void selectRecord(ListGrid grid, String field, String value) {
        for (ListGridRecord record : grid.getRecords()) {
            if (record.getAttribute(field).equals(value)) {
                grid.selectRecord(record);
            }
        }
    }
    
    public static void debug(String message) {
        GWT.log(message);
    }
    
    public static void selectGridIfSingleRecord(ListGrid grid) {
        if (grid.getRecords().length == 1) {
            grid.selectRecord(0);
        }
    }
    
    public static String decodeLookupCode(Map<String, String> map, String code) {
        if (isEmpty(code) || map.get(code) == null) {
            return code;
        }
        
        return map.get(code);
    }
    
}
